package com.central.task.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.central.task.mapper.TaskDefinedLogMapper;
import com.central.task.mapper.TaskDefinedMapper;
import com.central.task.model.TaskDefined;
import com.central.task.model.TaskDefinedLog;
import com.central.task.service.IResourceManageService;
import com.central.task.service.ITaskDefinedService;
import com.central.common.feign.SchedulerService;
import com.central.common.feign.UserService;
import com.central.common.model.*;
import com.central.common.service.impl.SuperServiceImpl;
import com.central.common.utils.UserRoleUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author Tindy
 * @date 2021/11/29
 * @describe
 */
@Slf4j
@Service
public class TaskDefinedServiceImpl extends SuperServiceImpl<TaskDefinedMapper, TaskDefined> implements ITaskDefinedService {
    @Autowired
    private UserService userService;
    @Autowired
    private SchedulerService schedulerService;
    @Autowired
    private TaskDefinedLogMapper taskDefinedLogMapper;
    @Autowired
    private IResourceManageService resourceManageService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result saveOrUpdateTask(SysUser user, TaskDefined taskDefined) {
        TaskDefined taskDefined2 = getById(taskDefined.getId());
        if(taskDefined2!=null){
            if(checkOperationPermission(user,taskDefined2)){
                saveOrUpdate(taskDefined);
                return Result.succeed("操作成功");
            }else {
                return Result.failed("操作失败，用户权限不足");
            }
        }else {
            taskDefined.setProId(user.getCurrentProjectId());
            taskDefined.setProName(user.getProName());
            saveOrUpdate(taskDefined);
            return Result.succeed("操作成功");
        }
    }

    @Override
    public PageResult<TaskDefined> findTasks(Long proId, Map<String, Object> params) {
        Page<TaskDefined> page = new Page<>(MapUtils.getInteger(params, "page"), MapUtils.getInteger(params, "limit"));
        List<TaskDefined> list = baseMapper.findTasks(page, proId,params);
        long total = page.getTotal();
        return PageResult.<TaskDefined>builder().data(list).code(0).count(total).build();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result delTask(SysUser user, Long taskId) {
        //判断该作业是否有版本已发布，已发布，不可删除
        if(schedulerService.taskIsRelease(taskId,null)!=0l){
            return Result.failed("该作业有版本已发布，不可删除");
        }
        TaskDefined taskDefined = getById(taskId);
        if(checkOperationPermission(user,taskDefined)){
            removeById(taskId);
            //删除作业所有版本详细
            List<TaskDefinedLog> taskDefinedLogs = taskDefinedLogMapper.selectList(new QueryWrapper<TaskDefinedLog>().eq("task_defined_id", taskId));
            ArrayList<Long> taskDefinedLogIds = new ArrayList<>();
            ArrayList<Long> resourceQuoteIds = new ArrayList<>();
            for (TaskDefinedLog taskDefinedLog : taskDefinedLogs) {
                taskDefinedLogIds.add(taskDefinedLog.getId());
                resourceQuoteIds.addAll(taskDefinedLog.getTaskParams().getResourceQuoteIds());
            }
            if(!CollectionUtils.isEmpty(taskDefinedLogIds)) taskDefinedLogMapper.deleteBatchIds(taskDefinedLogIds);
            if(!CollectionUtils.isEmpty(resourceQuoteIds)) resourceManageService.delQuotes(resourceQuoteIds);
            return Result.succeed("操作成功");
        }else {
            return Result.failed("操作失败，用户权限不足");
        }
    }

    @Transactional
    @Override
    public Result delTaskLog(SysUser user, Long taskLogId) {
        //判断该作业版本是否已发布，已发布，不可删除
        if(schedulerService.taskIsRelease(null,taskLogId)!=0l){
            return Result.failed("该作业版本已发布，不可删除");
        }
        TaskDefinedLog taskDefinedLog = taskDefinedLogMapper.selectById(taskLogId);
        TaskDefined taskDefined = getById(taskDefinedLog.getTaskDefinedId());
        if(checkOperationPermission(user,taskDefined)){
            taskDefinedLogMapper.deleteById(taskLogId);
            List<Long> resourceQuoteIds = taskDefinedLog.getTaskParams().getResourceQuoteIds();
            //删除资源引用
            if(!CollectionUtils.isEmpty(resourceQuoteIds)) resourceManageService.delQuotes(resourceQuoteIds);
            return Result.succeed("操作成功");
        }else {
            return Result.failed("操作失败，用户权限不足");
        }
    }

    @Override
    public List<String> getOwners(Long taskDefinedId) {
        TaskDefined taskDefined = getById(taskDefinedId);
        if(taskDefined!=null){
            return taskDefined.getOwners();
        }else {
            return Collections.emptyList();
        }
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result saveTaskLog(TaskDefinedLog taskDefinedLog) {
        //获取资源引用id
        taskDefinedLog.getTaskParams().setResourceQuoteIds(getResourceQuoteIds(taskDefinedLog));
        Integer version = taskDefinedLogMapper.queryMaxVersionForDefined(taskDefinedLog.getTaskDefinedId());
        int insertVersion = version == null || version == 0 ? 1 : version + 1;
        taskDefinedLog.setVersion(insertVersion);
        taskDefinedLogMapper.insert(taskDefinedLog);
        return Result.succeed("操作成功");
    }

    /**
     * 获取资源引用id
     * @param taskDefinedLog
     * @return
     */
    private List<Long> getResourceQuoteIds(TaskDefinedLog taskDefinedLog) {
        ArrayList<Long> result = new ArrayList<>();
        List<Long> resourceIds = taskDefinedLog.getTaskParams().getResourceIds();
        if(resourceIds!=null){
            for (Long resourceId : resourceIds) {
                Long quoteId= resourceManageService.quoteResource(resourceId,"task id:"+taskDefinedLog.getTaskDefinedId()+"-version:"+taskDefinedLog.getVersion());
                result.add(quoteId);
            }
        }
        return result;
    }

    @Override
    public List<TaskDefinedLog> findTaskLogs(Long taskDefinedId) {
        Long taskDefinedLogId = schedulerService.taskIsRelease(taskDefinedId, null);
        return taskDefinedLogMapper.findTaskLogs(taskDefinedId,taskDefinedLogId);
    }

    @Override
    public Result release(TaskDefinedLog taskDefinedLog) {
        TaskDefined taskDefined = getById(taskDefinedLog.getTaskDefinedId());
        TaskDefinition taskDefinition = new TaskDefinition();
        taskDefinition.setTaskDefinedId(taskDefined.getId());
        taskDefinition.setTaskDefinedLogId(taskDefinedLog.getId());
        taskDefinition.setName(taskDefined.getName());
        taskDefinition.setDescription(taskDefined.getDescription());
        taskDefinition.setTaskType(taskDefined.getTaskType());
        taskDefinition.setProId(taskDefined.getProId());
        taskDefinition.setProName(taskDefined.getProName());
        taskDefinition.setVersion(taskDefinedLog.getVersion());
        taskDefinition.setTaskContent(JSONUtil.toJsonStr(taskDefinedLog.getTaskContent()));
        taskDefinition.setTaskParams(taskDefinedLog.getTaskParams());
        taskDefinition.setOwners(taskDefined.getOwners());
        taskDefinition.setIsTmp(false);
        return schedulerService.release(taskDefinition);
    }

    @Override
    public TaskDefinedLog getTaskLog(Long taskDefinedLogId) {
        return taskDefinedLogMapper.selectById(taskDefinedLogId);
    }

    @Override
    public Result tmpRunTask(TaskDefinedLog taskDefinedLog) {
        TaskDefined taskDefined = getById(taskDefinedLog.getTaskDefinedId());
        TaskDefinition taskDefinition = new TaskDefinition();
        taskDefinition.setTaskDefinedId(taskDefined.getId());
        taskDefinition.setName(taskDefined.getName());
        taskDefinition.setDescription(taskDefined.getDescription());
        taskDefinition.setTaskType(taskDefined.getTaskType());
        taskDefinition.setProId(taskDefined.getProId());
        taskDefinition.setProName(taskDefined.getProName());
        taskDefinition.setVersion(taskDefinedLog.getVersion());
        taskDefinition.setTaskContent(JSONUtil.toJsonStr(taskDefinedLog.getTaskContent()));
        taskDefinition.setTaskParams(taskDefinedLog.getTaskParams());
        taskDefinition.setOwners(taskDefined.getOwners());
        taskDefinition.setIsTmp(true);
        return schedulerService.tmpRunTask(taskDefinition);
    }




    /**
     * 只有项目管理员和任务负责人拥有修改权限
     * @param user
     * @param taskDefined
     * @return
     */
    private boolean checkOperationPermission(SysUser user, TaskDefined taskDefined) {
        if(user.getCurrentProjectId().equals(taskDefined.getProId()) && UserRoleUtil.checkProAdmin(user.getProRoles())) return true;
        if(taskDefined.getOwners().contains(user.getUsername())) return true;
        return false;
    }
}
